import json
import random
import re
import urllib
from collections import defaultdict
from datetime import timedelta, datetime
from json import JSONDecodeError
import os
import aiohttp
import time
import sys
import aioredis
import lxml.html
import pymongo
from phone import Phone
from tornado import gen
import asyncio
from faker import Faker

INTEVAL = 0.2
QUERY_TIME = 60 * 5
lock = asyncio.Lock()

from baseHandler import init_logger, PayHandler, Application

card = {'100': {'cardValCode': '04',
                'cardValue': '10000',
                'offerRate': '1',
                'offerRateId': ''},
        '20': {'cardValCode': '01',
               'cardValue': '2000',
               'offerRate': '1',
               'offerRateId': ''},
        '30': {'cardValCode': '02',
               'cardValue': '3000',
               'offerRate': '1',
               'offerRateId': ''},
        '300': {'cardValCode': '05',
                'cardValue': '30000',
                'offerRate': '1',
                'offerRateId': ''},
        '50': {'cardValCode': '03',
               'cardValue': '5000',
               'offerRate': '1',
               'offerRateId': ''}}

RECHANGE_QUEUE = defaultdict(asyncio.Queue)


def get_ts():
    return str(time.time()).replace('.', '')[:13]


async def get_unicom_wx(user_tel, amount, upay_id, redis, ticket=''):
    faker = Faker(locale='zh_CN')
    ip = faker.ipv4()
    headers = {'Cookie': 'upay_user=%s;' % upay_id, 'Host': 'upay.10010.com',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0',
               # "User-Agent": "Mozilla/5.0 (Linux; Android 7.0; MI 5s Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36 wxwork/2.4.16 MicroMessenger/6.3.22 NetType/WIFI Language/zh",
               'X-Requested-With': 'XMLHttpRequest',
               'Referer': 'http://upay.10010.com/npfwap/npfMobWap/bankcharge/index.html?version=wap&desmobile=6672070486447365',
               # 'CLIENT-IP': ip,
               # 'X-FORWARDED-FOR': ip,
               }

    proxys = await redis.smembers('un_proxy', encoding='utf-8')
    if not proxys:
        return {"code": -1, "message": "无可用代理"}
    proxy = random.choice(list(proxys))
    logger.info("代理%s|%s", user_tel, proxy)
    if proxy:
        conn = proxy
    else:
        conn = None
    logger.info(conn)
    async with aiohttp.ClientSession(headers=headers) as session:
        prov_url = 'http://upay.10010.com/npfwap/npfMobWeb/getArea/init?callback=jQuery&commonBean.phoneNo=%s&_=%s' % (user_tel, get_ts())
        async with session.get(prov_url, proxy=conn, timeout=5) as rsp:
            body = await rsp.text()
            area = re.findall('(\d+)', body)
            prov = body.split('X')[2]

        unused = await redis.sismember("unused_un_prov", prov)
        if unused:
            logger.info("%s交费不可用", prov)
            return {"code": -1, "message": "%s交费不可用" % prov}
        if not area:
            return {"code": -1, "message": rsp.content.decode()}
        card_info = card.get(str(amount), {})
        if card_info:
            bussine_type = '06'
            userChooseMode = '0'
            url = 'http://upay.10010.com/npfwap/NpfMob/mobWapBankCharge/wapBankChargeCheck.action'
            url2 = 'http://upay.10010.com/npfwap/NpfMob/mobWapBankCharge/wapBankChargeSubmit.action'
        else:
            bussine_type = '01'
            userChooseMode = ''
            url = 'http://upay.10010.com/npfwap/NpfMob/mobWapBankPay/mobWapPayFeeCheck.action'
            url2 = 'http://upay.10010.com/npfwap/NpfMob/mobWapBankPay/mobWapPayFeeApply.action'
        data = {
            'browserVersion': '',
            'bussineTypeInput': '0',
            'cardBean.cardValue': card_info.get('cardValue', ''),
            'cardBean.cardValueCode': card_info.get('cardValCode', ''),
            'channelKey': '',
            'commonBean.activityType': '',
            'commonBean.areaCode': '',
            'commonBean.bussineType': bussine_type,
            'commonBean.channelCode': 'DEBIT_YEEPAYWAP',
            'commonBean.channelType': '307',
            'commonBean.cityCode': area[1],
            'commonBean.netAccount': '',
            'commonBean.offerate': card_info.get('offerRate', ''),
            'commonBean.offerateId': card_info.get('offerateId', ''),
            'commonBean.orgCode': '01',
            'commonBean.payAmount': amount,
            'commonBean.phoneNo': user_tel,
            'commonBean.provinceCode': area[0],
            'commonBean.reserved1': 'false',
            'commonBean.ticketNo': '',
            'commonBean.userChooseMode': userChooseMode,
            'invoiceBean.card_type': '',
            'invoiceBean.id_cardno': '',
            'invoiceBean.invoice_head': '',
            'invoiceBean.invoice_type': '',
            'invoiceBean.is_mailing': '0',
            'invoiceBean.need_invoice': '0',
            'numberType': '',
            'pointBean.payMethod': '',
            'pointBean.pointNumber': '',
            'ticketNew': ticket,
        }
        # print(data)
        # url = 'http://upay.10010.com/npfwap/NpfMob/mobWapBankCharge/wapBankChargeCheck.action'
        async with session.post(url, data=data, headers=headers, proxy=conn) as rsp:
            res = await rsp.text()
            res = json.loads(res)
            logger.info(res)
            if res['out'] != 'success':
                # if res['out'] == "您的操作太频繁，请稍后再试！":
                #     await redis.srem("un_proxy", proxy)
                return {"code": -1, "message": res['out']}
            secstate = res['secstate']

        # url2 = 'http://upay.10010.com/npfwap/NpfMob/mobWapBankCharge/wapBankChargeSubmit.action'
        data2 = {'browserVersion': '',
                 'channelKey': '',
                 'commonBean.phoneNo': user_tel,
                 'commonBean.provinceCode': area[0],
                 'secstate.state': secstate,
                 'ticketNew': ticket}
        async with session.post(url2, data=data2, headers=headers, proxy=conn) as rsp:
            res = await rsp.text()
            # logger.info(res)
            res = json.loads(res)
            # print(res)
            pay_url = res['payUrl']

            # logger.info(pay_url)
        head2 = {'Host': 'unipay.10010.com',
                 'Referer': 'http://upay.10010.com/npfwap/npfMobWap/bankcharge/index.html?version=wap&desmobile=6672070486447365',
                 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0'}
        mini_wap_url = "http://unipay.10010.com/udpPortal/miniwappayment/miniWapPaymentChoose.action?" + urllib.parse.urlparse(pay_url).query
        # logger.info(mini_wap_url)
        async with session.get(mini_wap_url, headers=head2, proxy=conn) as rsp:
            body = await rsp.text()
            root = lxml.html.fromstring(body)
            inputs = root.xpath("//input")
            data = {i.name: i.value for i in inputs}
            channel = root.xpath('//*[@id="miniwappayment"]/article/section[2]/div[2]')
            channel = channel[0].attrib['paychannel']
            data['paymentInfo.bankSelect'] = channel
            data['bankSelect'] = data.get('paymentInfo.bankSelect')
            # data['ServicePlantFormId'] = '10'
            # logger.info(data)
        result_url = 'https://unipay.10010.com/udpPortal/miniwappayment/miniWapPaymentAffirm.action'
        logger.info(result_url)
        head2['Host'] = 'unipay.10010.com'
        head2["Referer"] = mini_wap_url
        head2['Upgrade-Insecure-Requests'] = "1"
        async with session.post(result_url, data=data, headers=head2, proxy=conn) as rsp:
            logger.info(rsp.headers)
            body = await rsp.text()
            # logger.info(body)
            url = re.findall('"(weixin.*)"', body)
            # logger.info(url)
            query_url = re.findall('redirect_url="(.*)"', body)[0]
            logger.info(url)
            # query_url = query_url.replace("%22", "")
        async with session.post(query_url, headers=head2, proxy=conn) as rsp:
            text = await rsp.text()
            root = lxml.html.fromstring(text)
            ele = root.xpath('/html/body/div/a[1]')[0]
            # query_url = 'https://unipay.10010.com/udpPortal/payment/' + ele.attrib['href']
            p = urllib.parse.urlparse(str(rsp.url))
            query_url = '%s://%s%s/%s' % (p.scheme, p.hostname, os.path.split(p.path)[0], ele.attrib['href'])

            return {"code": 0, "url": url[0], "query_url": query_url, "prov": prov}


async def unicom_reuslt(query_url):
    headers = {'Host': 'upay.10010.com',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0'}
    # p = urllib.parse.urlparse(query_url)
    # query_url = 'https://unipay.10010.com/udpNewPortal/miniwappayment/weixinH5Return?' + p.query
    # query_url = 'https://unipay.10010.com/udpPortal/payment/weixinH5Return.action?' + p.query
    # logger.info(query_url)

    async with aiohttp.ClientSession(headers=headers) as session:
        async with session.get(query_url) as rsp:
            body = await rsp.text()
            # logger.info(body)
            root = lxml.html.fromstring(body)
            form = root.xpath('//form[@name="form1"]')
            if form:
                url = form[0].attrib['action']
                inputs = root.xpath('//input')
                data = {i.attrib['name']: i.attrib['value'] for i in inputs}
                headers['Referer'] = query_url
                async with session.get(url, params=data, headers=headers) as rsp:
                    body = await rsp.text()
                    # logger.info(body)
                    root = lxml.html.fromstring(body)

            order_no = root.xpath('//*[@id="actiOrderNo"]')
            message = ""
            if order_no:
                message = order_no[0].text
            # ele = root.xpath("/html/body/article/h6/span")
            ele = root.xpath('//li[@class="enlarge"]/span')
            if ele:
                text = ele[0].text
                if '充值成功' in text:
                    orderstate = '0'
                    # pay_time = root.xpath("/html/body/article/ul/li[4]/span[2]")
                    # pay_time_text = ""
                    # if pay_time:
                    #     pay_time_text = pay_time[0].text
                    return orderstate, message or text
            else:
                err_ele = root.xpath("/html/body/div/p/span")
                if '订单支付失败' in err_ele[0].text:
                    orderstate = '8'
                    message = "未支付"
                    return orderstate, message

            return "9", message


async def get_wxh5_link(obj, conn_unicom, conn, timeout=30):
    ticket_count = 5
    while ticket_count:
        try:
            n = 5
            while n:
                upay_data_s = await conn_unicom.rpop('tickets')
                logger.info(upay_data_s)
                if upay_data_s:
                    upay_data = json.loads(upay_data_s.decode())
                    break
                else:
                    await asyncio.sleep(1)
                    n -= 1
            if not upay_data_s:
                logger.info("增加upay")
                return {"code": "-1", "message": "验证码异常"}

            upay = upay_data["upay"]
            ticket = upay_data['ticket']
            logger.info("下单%s|%s", upay, obj['ordernumber'])
            future = get_unicom_wx(obj["tel_number"], obj['amount'], upay, conn, ticket)
            result = await gen.with_timeout(timedelta(seconds=timeout), future)
        except aiohttp.ClientConnectorError as e:
            logger.info("%s|代理失效", obj["tel_number"])
            result = {'code': -1, 'message': "proxy error"}
        except aiohttp.client_exceptions.ClientOSError:
            logger.info("%s|代理失效2", obj["tel_number"])
            result = {'code': -1, 'message': "proxy error2"}
        except aiohttp.client_exceptions.ServerDisconnectedError:
            logger.info("%s|代理失效3", obj["tel_number"])
            result = {'code': -1, 'message': "proxy error3"}
        except JSONDecodeError as e:
            logger.error(e, exc_info=True)
            result = {'code': -1, 'message': "proxy error4"}
        except Exception as e:
            logger.info("%s|取单失败|%s", obj["tel_number"], logger.info(type(e).__name__))
            logger.error(e, exc_info=True)
            result = {'code': -2, 'message': "error"}

        logger.info("%s|%s|%s|%s", upay, upay_data.get('addDate'), obj["tel_number"], result.get("message"))
        if result['code'] == 0:
            conn_unicom.lpush('tickets', json.dumps(upay_data))
            break
        elif result['code'] == -2:
            conn_unicom.rpush('tickets', json.dumps(upay_data))
            break
        else:
            if "验证码校验异常" in result.get("message", ""):
                pass
            elif "proxy error" not in result.get("message", ""):
                conn_unicom.rpush('tickets', json.dumps(upay_data))
            else:
                conn_unicom.lpush('tickets', json.dumps(upay_data))
            if "proxy error" in result.get("message", ""):
                pass
            # elif "操作太频繁" in result.get("message", ""):
            #     pass
            elif "验证码校验异常" not in result.get("message", ""):
                break

            ticket_count -= 1

    return result


class UniWxHandler(PayHandler):
    @gen.coroutine
    def post(self):
        # s_time = self.application.redis.hget("forbidden_time", "start")
        # e_time = self.application.redis.hget("forbidden_time", "end")
        # now = datetime.now()
        # now_seconds = now.hour * 60 * 60 + now.minute * 60 + now.second
        # if s_time and e_time:
        #     if int(s_time) < now_seconds < int(e_time):
        #         return self.write(json.dumps({"message": "不在交易时间内", "ret": -1}))
        db = self.application.db
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        logger.info(data)
        arguments = ["payorderno", "amount"]
        for arg in arguments:
            if arg not in data:
                return self.write({"ret": -1, "message": "缺少%s" % arg})

        is_close = yield self.application.redis.get("is_unicom_close", encoding='utf-8')
        if is_close == '1':
            logger.info("%s|通道关闭" % data["payorderno"])
            return self.write({"ret": -1, "message": "通道关闭"})

        token = yield self.application.redis.rpop("jiaoyi")
        if not token:
            return self.write({"message": "交易太频繁", "ret": -1})

        obj = yield db.rechange.find_one({"payorderno": data["payorderno"]})

        if obj:
            logger.info(obj)
            return self.write({"message": "订单号重复", "ret": -1})
        logger.info("支付订单%s|%s|%s", self.merchantid, data["payorderno"], data['amount'])
        supplier = self.merchant_info.get("supplier")
        if not supplier:
            return self.write({"message": "无有效供应商", "ret": -1})

        while True:
            # if data["amount"] in ('50', '100'):
            queue_name = "UN_%s_%s" % (supplier, data["amount"])
            pre_queue_name = "PRE_UN_%s_%s" % (supplier, data["amount"])

            result = yield self.application.redis.rpop(pre_queue_name, encoding='utf-8')
            if result:
                result = json.loads(result)
                ordernumber = result.get("ordernumber")
                if time.time() - result["time"] > 175:
                    logger.info("%s超过支付时间" % ordernumber)
                    continue
                logger.info("预|%s|%s|%s", pre_queue_name, ordernumber, data["payorderno"])
            else:
                logger.info(queue_name)
                # obj = RECHANGE_QUEUE[queue_name].get_nowait()
                obj = yield self.application.redis.rpop(queue_name, encoding='utf-8')

                # logger.info(obj)
                if not obj:
                    return self.write({'ret': -1, 'message': "无有效订单"})
                obj = json.loads(obj)

                if time.time() - obj["time"] > 58:
                    logger.info("%s超过取单时间" % obj["ordernumber"])
                    if time.time() - obj['time'] < 60:

                        yield db.rechange.update_one({"ordernumber": obj["ordernumber"]},
                                                     {"$set": {
                                                         "orderstate": "1"
                                                     }})
                    continue
                yield db.rechange.update_one({"ordernumber": obj["ordernumber"]},
                                             {"$set": {
                                                 "orderstate": "8"
                                             }})
                result = yield get_wxh5_link(obj, self.application.redis_unicom, self.application.redis)
                ordernumber = obj["ordernumber"]

            recharge_obj = yield db.rechange.find_one({"ordernumber": ordernumber})
            if recharge_obj.get("payorderno"):
                return self.write({'ret': -1, 'message': "无效订单"})

            if result['code'] == 0:
                orderstate = '8'
                wx_url = result['url']
                query_url = result['query_url']
                # url = 'http://hh.91info.info:8080/charge/pay.php?orderNubmer=%s' % ordernumber
                url = 'http://qr.nsdmkn.com/charge/pay.php?orderNubmer=%s' % ordernumber
                yield db.rechange.update_one({"ordernumber": ordernumber},
                                             {"$set": {
                                                 "payorderno": data["payorderno"],
                                                 "merchantuid": self.merchantid,
                                                 "orderstate": orderstate,
                                                 "orderid": query_url,
                                                 "wx_url": wx_url,
                                                 "pay_backurl": data.get("backurl"),
                                                 "message": result.get('message', ''),
                                                 "prov": result.get("prov")
                                             }
                                             })
            else:
                orderstate = '1'
                url = ''
                query_url = ''
                yield db.rechange.update_one({"ordernumber": ordernumber},
                                             {"$set": {
                                                 "orderstate": orderstate,
                                                 "message": result.get('message', '')
                                             }
                                             })
            res = {"orderstate": orderstate, "message": result.get('message', ''), 'wx_url': url,
                   "query_url": query_url}

            return_obj = self.niti_data(res, {"MERCHANTID": self.merchantid})
            return_obj.update({"ret": 0, "message": "success"})
            self.write(return_obj)
            self.finish()
            return


class UnRechargeHandler(PayHandler):
    @gen.coroutine
    def post(self):
        logger.info(self.request.path)
        db = self.application.db
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        logger.info(data)
        arguments = ["ordernumber", "amount", "tel_number"]
        for arg in arguments:
            if arg not in data:
                return self.write({"ret": -1, "message": "缺少%s" % arg})
        logger.info("充值%s|%s|%s", data['ordernumber'], data['tel_number'], data['amount'])

        is_risk = yield self.application.redis.sismember("risk_number", data["tel_number"])
        if is_risk:
            logger.info("不到账%s" % data["tel_number"])
            return self.write({"ret": -1, "message": "风险号码"})

        p = Phone()
        prov_res = p.find(data['tel_number'])
        if prov_res:
            logger.info(prov_res)
            unused = yield self.application.redis.sismember("unused_un_prov", prov_res.get("province"))
            if unused:
                logger.info("%s交费不可用", prov_res.get("province"))
                return self.write({"ret": -1, "message": "该省交易暂停"})

        res = self.check_ordernumber(data)
        if res:
            return self.write(res)
        start_time = time.time()

        obj = {
            "tel_number": data["tel_number"],
            "ordernumber": data["ordernumber"],
            "time": start_time,
            "amount": data["amount"],
            "tel_type": "unicom"
        }

        data['time'] = start_time
        data["orderdate"] = datetime.now().strftime('%Y%m%d')
        data["merchantid"] = self.merchantid
        data['tel_type'] = 'unicom'
        data['orderstate'] = '2'
        try:
            yield db.rechange.insert_one(data)
            self.application.redis.lpush('unicom_recharge', json.dumps({"ordernumber": data['ordernumber']}))
        except pymongo.errors.DuplicateKeyError:
            return self.write({"ret": -1, "message": "重复的订单号"})

        if data["amount"] in ('10', '20', '30', '50', '100', '200', '300', '500'):
            queue_name = "UN_%s_%s" % (self.merchantid, data["amount"])
            queue_size = yield self.application.redis.llen(queue_name)
            res = {"orderstate": '2', "message": "订单提交成功", }
            return_obj = self.niti_data(res, {"MERCHANTID": self.merchantid})
            return_obj.update({"ret": 0, "message": "success"})
            self.write(return_obj)
            self.finish()
            if data["amount"] in ("30", "50", "100", "200"):
                pre_queue_name = "PRE_UN_%s_%s" % (self.merchantid, data["amount"])
                pre_queue_size = yield self.application.redis.llen(pre_queue_name)
                pre_un_queue_len_name = "pre_un_queue_len_%s_%s" % (self.merchantid, data["amount"])
                pre_size = yield self.application.redis.get(pre_un_queue_len_name, encoding='utf-8')
                if pre_size:
                    pre_size = int(pre_size)
                else:
                    pre_size = 30
                logger.info("当前队列%s长度%s, 设置长度%s", pre_queue_name, pre_queue_size, pre_size)
                if pre_queue_size < pre_size:
                    # yield self.application.redis.set(pre_un_queue_len_name,  pre_size - 1)
                    yield db.rechange.update_one({"ordernumber": data["ordernumber"]},
                                                 {
                                                     "$set": {
                                                            "orderstate": '8',
                                                        }
                                                 })
                    result = yield get_wxh5_link(obj, self.application.redis_unicom, self.application.redis, timeout=30)
                    if result['code'] == 0:
                        yield db.rechange.update_one({"ordernumber": data["ordernumber"]},
                                                     {"$set": {
                                                         "orderstate": '8',
                                                         "orderid": result.get('query_url'),
                                                         "wx_url": result.get('url'),
                                                         "message": result.get('message', ''),
                                                         "prov": result.get("prov")
                                                     }
                                                     })
                        obj.update(result)
                        logger.info(pre_queue_name)
                        yield self.application.redis.lpush(pre_queue_name, json.dumps(obj))
                    else:
                        yield db.rechange.update_one({"ordernumber": data["ordernumber"]},
                                                     {
                                                         "$set": {
                                                             "orderstate": '1',
                                                             "message": result.get('message', '')
                                                         }
                                                     })
                    # pre_size = yield self.application.redis.get(pre_un_queue_len_name, encoding='utf-8')
                    # pre_size = int(pre_size)
                    # yield self.application.redis.set(pre_un_queue_len_name, pre_size + 1)
                else:
                    if queue_size > 30:

                        logger.info("%s队列已满", data['ordernumber'])
                        yield db.rechange.update_one({"ordernumber": data["ordernumber"]},
                                                     {
                                                         "$set": {
                                                             "orderstate": '1',
                                                             "message": "队列已满"
                                                         }
                                                     })
                    else:
                        yield self.application.redis.lpush(queue_name, json.dumps(obj))
                    # return self.write({"ret": -1, "message": "队列已满"})
            else:
                yield self.application.redis.lpush(queue_name, json.dumps(obj))

            logger.info(queue_size)
        else:
            return self.write({"message": "不支持的金额", "ret": -1})


async def query(query_obj, db, redis):
    now = time.time()
    obj = await db.rechange.find_one(query_obj)
    extra = {}
    if not obj:
        orderstate = "1"
        message = "订单号不存在"
        return orderstate, message, extra

    orderstate = obj.get("orderstate", "2")

    if orderstate in ("0", "1", "5", "6"):
        message = obj.get("message", "")
        extra = {
            "tel_number": obj["tel_number"],
            "orderid": obj.get("orderid", ""),
        }
    else:
        async with lock:
            obj = await db.rechange.find_one(query_obj)
            query_time = obj.get("query_time") or obj["time"]
            if time.time() - query_time < 15:
                message = ""
                return orderstate, message, extra

            query_time = time.time()
            await db.rechange.update_one(query_obj, {"$set": {"query_time": query_time}})

        if obj.get('wx_url'):
            # if obj.get("tel_type", "") == 'unicom':
            orderstate, message = await unicom_reuslt(obj['orderid'])
            if orderstate == '9':
                await redis.sadd("unicom_9", obj['ordernumber'])
            if orderstate == '8':
                if query_time - obj['time'] > QUERY_TIME:
                    orderstate = '1'
                else:
                    orderstate = obj.get("orderstate")
            extra = {
                "tel_number": obj["tel_number"],
                "orderid": obj.get("orderid", ""),
                # "url": obj.get("url", "")
            }
        else:
            if time.time() - obj['time'] < 60 and obj.get('orderstate', '2') == '2':
                orderstate = '2'
                message = obj.get("message", "取单中")
            elif time.time() - obj['time'] < 92 and obj.get('orderstate', '2') == '8':
                orderstate = '8'
                message = '获取二维码中'
            else:
                orderstate = '1'
                message = '未支付2'
            extra = {
                "tel_number": obj["tel_number"],
                "orderid": obj.get("orderid", ""),
                # "url": obj.get("url", "")
            }
        await db.rechange.update_one(query_obj, {
            "$set": {"orderstate": orderstate, "query_time": query_time, "message": message}})
    return orderstate, message, extra


class UnicomQuery(PayHandler):
    @gen.coroutine
    def post(self):
        db = self.application.db
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)

        if data.get("ordernumber"):
            query_obj = {"ordernumber": data["ordernumber"]}
        elif data.get("payorderno"):
            query_obj = {"payorderno": data["payorderno"]}

        else:
            return self.write({"message": "无效参数", "ret": -1})
        orderstate, message, extra = yield query(query_obj, db, self.application.redis)
        logger.info("查询%s|%s|%s|%s", data.get("ordernumber"), data.get("payorderno"), orderstate, message)
        res = {"orderstate": orderstate, "message": message, **extra}
        return_obj = self.niti_data(res, {"MERCHANTID": self.merchantid})
        return_obj.update({"ret": 0, "message": "success"})
        self.write(return_obj)


if __name__ == "__main__":
    handlers = [
        (r"/pay/un_recharge", UnRechargeHandler),
        (r"/pay/un_wxqrcode", UniWxHandler),
        (r"/pay/un_query", UnicomQuery),
        # (r"/pay/queue", QueueHandler),
        # (r"/set_querytime/(\d+)", SetTimeHandler)
    ]
    QUERY_TIME = 60 * 5
    application = Application(handlers, debug=False)
    port = sys.argv[1]
    application.listen(port, address="127.0.0.1")
    logger = init_logger("cmcc", "/app/log/cs_unicom/unicom%s.log" % port) 
    logger.info("Run unionpay server ... http://127.0.0.1:%s", port)
    loop = asyncio.get_event_loop()
    application.redis = loop.run_until_complete(
        aioredis.create_redis(address=('localhost', 6379), db=0, loop=loop)
    )
    application.redis_unicom = loop.run_until_complete(
        aioredis.create_redis(address=('localhost', 6379), db=1, loop=loop)
    )
    application.init_with_loop(loop)
    loop.run_forever()
